/*
@title: crappy_bird
@description: Crappy bird is a rendition of flappy bird! Try to get as far as you can without hitting the walls that come scrolling at you!
@author: ced
@tags: ['endless','retro']
@addedOn: 2022-07-14
*/

const NORMAL_TICK_FREQ = 200;
const MAX_INPUT_FREQ = 100;

const mod = (f, n) => ((f % n) + n) % n;

const flapUp = "d";
const flapDown = "p";
const wall = "w";

const bird = () => getFirst("d") || getFirst("p");

setLegend(
  [ flapUp, bitmap`
...0000000......
..033333330.....
.0333333330.....
.03333000330....
.03300333330....
..0333333330....
...003333330....
.....0033330....
.......0330.....
......030030....
.....03333360...
.....033333660..
......0333300...
.......0000.....
................
................`],
  [ flapDown, bitmap`
................
......0000......
.....033330.....
....03333360....
....030333660...
.....0030300....
......0330......
.....033330.....
.....033330.....
....03333330....
....03333330....
...0333333330...
...0333333330...
...0333333330...
....00000000....
................`],
  [ wall, bitmap`
.0000.000000.000
0....0......0...
0....0......0...
0....0......0...
.0000.000000.000
................
00.0000.00000.00
..0....0.....0..
..0....0.....0..
..0....0.....0..
00.0000.00000.00
................
0000.0000.00000.
....0....0.....0
....0....0.....0
....0....0.....0
 `],
);

const levels = [
    map`
.................www
..................ww
....................
....................
....................
....................
....................
....................
d...................
....................
....................
....................
....................
.................www
.................www
.................www
.................www
.................www
.................www
.................www`,
    map`
.......www..........
........ww..........
.......www..........
.......www..........
.......www..........
........ww..........
.......www..........
.......www..........
........w........w..
d...............www.
................www.
................www.
................www.
.................ww.
ww..................
www.................
www.............ww..
www.............www.
www.............www.
wwww...........wwww.`,
    map`
wwwwwwwwwwwwwwwwwwww
wwwwwwwwwwwwwwwwwwww
w......wwwwwwwwwwwww
........wwwww.......
.........wwww.......
..........ww........
..........w.........
....................
....................
d.............ww....
...............ww...
...............w....
......w........w....
....................
....................
w..................w
ww................ww
ww.w.....wwwwwwwwwww
ww.ww...wwwwwwwwwwww
wwwwwww.wwwwwwwwwwww`
];
let level = 0;

let nextTick, lastTick, alive, vel, ticksOnMap;
const startLevel = n => {
    ticksOnMap = 0;
    setMap(levels[Math.min(n, levels.length-1)]);
    vel = 2;
    alive = true;
    tick();
}

onInput("w", () => {
    const elapsed = Date.now() - lastTick;
    
    if (!alive && elapsed > 500) {
        start();
    }
    
    if (elapsed < MAX_INPUT_FREQ) return;
    vel = 3;
    tick();
});

let t = 0;
const tick = () => {
    if (!alive) return;

    t++;
    bird().type = [flapUp, flapDown][t % 2];
    
    /* birdy go up */
    if (bird()) {
        bird().y -= vel;
    }
    vel -= 1;

    ticksOnMap++;
    if (ticksOnMap > 40)
        startLevel(++level);

    /* walls wrap around */
    for (const w of getAll(wall)) {
        w.x = mod(w.x - 1, 20);
        if (getTile(w.x-1, w.y) == undefined)
            w.remove();
    }

    /* you hit wall, u die */
    if (bird()) {
        const {x, y} = bird();
        if (getTile(x, y).length > 1) {
            setMap(map`
....................
....................
....................
....................
.....w.w..w..w.w....
.....w.w.w.w.w.w....
......w..w.w.w.w....
......w..w.w.w.w....
......w...w..ww.w...
....................
....ww...www.ww.....
....w.w..w...w.w....
....w..w.www.w..w...
....w..w.w...w..w...
....www..www.www....
....................
....................`);
            alive = false;
        }
    }

    lastTick = Date.now();
    clearTimeout(nextTick);
    nextTick = setTimeout(tick, NORMAL_TICK_FREQ);
}

startLevel(0);
